package client;

import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;

import shared.Vertex;
import vmo.Actor;

public class Actor_Render_Unit {

	int []m_VAO,m_VBO,m_VIO;
	byte [][] m_colours;
	public Actor m_actor;
	Matrix4f m_matrix;
	
	public Actor_Render_Unit(Actor actor)
	{
		
		//the five are skin, clothing, hair, ear/tail, equipped, helmet
		m_actor=actor;
		m_matrix=new Matrix4f();
		m_matrix.m00=1;	m_matrix.m11=1; m_matrix.m22=1; m_matrix.m33=1;		
		RePosition();
		m_colours=new byte[6][];
		m_VBO=new int[6];
		m_VAO=new int[6];
		m_VIO=new int[6];
		for (int i=0;i<6;i++)
		{
			m_VAO[i]=GL30.glGenVertexArrays();
			GL30.glBindVertexArray(m_VAO[i]);
			
			m_VBO[i]=GL15.glGenBuffers();
			GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, m_VBO[i]);		
			
			
			//load from actor
			m_colours[i]=m_actor.getColor(i);
			//set VAO,VBO,VIO
			int d=m_actor.getSprite(i);
			//create arrays
			//build the vertex buffer here
			FloatBuffer verticesBuffer = BufferUtils.createFloatBuffer(4 * 6);
			//build indice buffer, it's not complex its a repeating pattern of six offset through the sequence
			IntBuffer indiceBuffer= BufferUtils.createIntBuffer(6);
	
			//precalc UV based on value
			int V=d/32;
			int U=d%32;
			float Uf=U*0.03125f;
			float Vf=V*0.0625f;
					
			Vertex v[]=new Vertex[4];
			v[0]=new Vertex(0, 0-2, 0, Uf, Vf);
			v[1]=new Vertex(0+1, 0-2, 0, Uf+0.03125F, Vf);
			v[2]=new Vertex(0+1, 0, 0, Uf+0.03125F, Vf+0.0625f);
			v[3]=new Vertex(0, 0, 0, Uf, Vf+0.0625f);				
			
			for (int j=0;j<4;j++)
			{
				verticesBuffer.put(v[j].pos);
				verticesBuffer.put(v[j].tex);				
			}
			int buffer[]=new int[6];
			buffer[0]=0;
			buffer[1]=1;
			buffer[2]=3;
			buffer[3]=1;
			buffer[4]=2;
			buffer[5]=3;				
			indiceBuffer.put(buffer);

			verticesBuffer.flip();	
			indiceBuffer.flip();
	
			GL15.glBufferData(GL15.GL_ARRAY_BUFFER, verticesBuffer, GL15.GL_STATIC_DRAW);
			
			GL20.glVertexAttribPointer(0, 4, GL11.GL_FLOAT, false, Vertex.size, 0);
			GL20.glVertexAttribPointer(1, 2, GL11.GL_FLOAT, false, Vertex.size,
			4 * 4);
			
			m_VIO[i]= GL15.glGenBuffers();
			GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, m_VIO[i]);
			GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indiceBuffer, GL15.GL_STATIC_DRAW);
			GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);				
			
		}
	}
	
	public void Redraw()
	{
		//buffer sub data to correct the layers
		for (int i=0;i<6;i++)
		{
			//load from actor			
			m_colours[i]=m_actor.getColor(i);
			//set VAO,VBO,VIO
			int d=m_actor.getSprite(i);
			//create arrays
			//build the vertex buffer here
			FloatBuffer verticesBuffer = BufferUtils.createFloatBuffer(4 * 6);
			//build indice buffer, it's not complex its a repeating pattern of six offset through the sequence

			//precalc UV based on value
			int V=d/32;
			int U=d%32;
			float Uf=U*0.03125f;
			float Vf=V*0.0625f;
					
			Vertex v[]=new Vertex[4];
			v[0]=new Vertex(0, 0-2, 0, Uf, Vf);
			v[1]=new Vertex(0+1, 0-2, 0, Uf+0.03125F, Vf);
			v[2]=new Vertex(0+1, 0, 0, Uf+0.03125F, Vf+0.0625f);
			v[3]=new Vertex(0, 0, 0, Uf, Vf+0.0625f);				
			
			for (int j=0;j<4;j++)
			{
				verticesBuffer.put(v[j].pos);
				verticesBuffer.put(v[j].tex);				
			}
			verticesBuffer.flip();	
			GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, m_VBO[i]);
			GL15.glBufferSubData(GL15.GL_ARRAY_BUFFER, 0,verticesBuffer);	
			GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
		}
	}
	
	public void Discard()
	{
		for (int i=0;i<6;i++)
		{
			if (m_VAO[i]!=-1)
			{
				GL30.glBindVertexArray(m_VAO[i]);
				GL20.glDisableVertexAttribArray(0);
				GL20.glDisableVertexAttribArray(1);
				if (m_VBO[i]!=-1)
				{
					GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
					GL15.glDeleteBuffers(m_VBO[i]);
				}
	
				if (m_VIO[i]!=-1)
				{
					GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
					GL15.glDeleteBuffers(m_VIO[i]);
				}		
				GL30.glBindVertexArray(0);
				GL30.glDeleteVertexArrays(m_VAO[i]);			
			}		
		}
	}
	
	public void Draw(FloatBuffer matrix44Buffer, int matrixloc,int colourloc)
	{

		if (m_actor.m_visible)
		{
			//set matrix
			m_matrix.store(matrix44Buffer); matrix44Buffer.flip();
			GL20.glUniformMatrix4(matrixloc, false, matrix44Buffer);
			for (int i=0;i<6;i++)
			{
				if (m_actor.hasPart(i))
				{
					//set colour
					GL20.glUniform4f(colourloc,(float)m_colours[i][0]/100,(float)m_colours[i][1]/100,(float)m_colours[i][2]/100, 1);				
					//link to array
					GL30.glBindVertexArray(m_VAO[i]);
					GL20.glEnableVertexAttribArray(0);
					GL20.glEnableVertexAttribArray(1);
					GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, m_VIO[i]);
					//draw, onwards	
					GL11.glDrawElements(GL11.GL_TRIANGLES, 6, GL11.GL_UNSIGNED_INT, 0);
					//unlink
					GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
					GL20.glDisableVertexAttribArray(0);
					GL20.glDisableVertexAttribArray(1);	
					GL30.glBindVertexArray(0);			
				}
			}
		}		
	}
	
	public void RePosition()
	{
		m_matrix.m30=0; m_matrix.m31=0;
		Vector3f vec=new Vector3f(); 
		vec.x=m_actor.getPosition().x; vec.y=m_actor.getPosition().y;
		Matrix4f.translate(vec, m_matrix,m_matrix);
		
	}
	
	
}
